package com.qh.resourcehub.program.firewall.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.qh.resourcehub.program.dto.FirewallDto;
import com.qh.resourcehub.program.dto.FirewallRuleDto;
import com.qh.resourcehub.program.entity.ApproveProcessDO;
import com.qh.resourcehub.program.entity.ApproveProcessRecordDO;
import com.qh.resourcehub.program.entity.FirewallDO;
import com.qh.resourcehub.program.entity.FirewallRuleDO;
import com.qh.resourcehub.program.firewall.service.FirewallService;
import com.qh.resourcehub.program.mapper.ApproveProcessMapper;
import com.qh.resourcehub.program.mapper.ApproveProcessRecordMapper;
import com.qh.resourcehub.program.mapper.FirewallMapper;
import com.qh.resourcehub.program.mapper.FirewallRuleMapper;
import com.qh.resourcehub.program.vo.FirewallRuleVo;
import com.qh.resourcehub.program.vo.FirewallVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class FirewallServiceImpl implements FirewallService {
    @Autowired
    private FirewallMapper firewallMapper;
    
    @Autowired
    private FirewallRuleMapper firewallRuleMapper;
    @Autowired
    private ApproveProcessMapper approveProcessMapper;

    @Autowired
    private ApproveProcessRecordMapper approveProcessRecordMapper;
    @Override
    public int ApplicationSave(FirewallDto dataDto) {
        int result = 0;
        if (!StringUtils.isEmpty(dataDto.getApplyUser()) && StringUtils.isEmpty(dataDto.getInfoId())){
            dataDto.setInfoId(UUID.randomUUID().toString().replace("-", ""));
            //新增流程表
            ApproveProcessDO approveProcessDO=new ApproveProcessDO();
            approveProcessDO.setInfoId(dataDto.getInfoId());//信息id
            approveProcessDO.setProcessStatus("00");//待提交
            approveProcessDO.setProcessTime(new Date());
            approveProcessDO.setProcessUser(dataDto.getApplyUser());
            approveProcessDO.setInfoType("4");
            approveProcessDO.setProcessId(UUID.randomUUID().toString().replace("-", ""));
            approveProcessDO.setProcessRecordId(UUID.randomUUID().toString().replace("-", ""));
            approveProcessMapper.insert(approveProcessDO);
            FirewallDO dataDo=new FirewallDO();
            BeanUtils.copyProperties(dataDto, dataDo);
            //新增基础表
            result=firewallMapper.insert(dataDo);
            List<FirewallRuleDto> rules=dataDto.getRules();
            for (FirewallRuleDto rule : rules) {
                FirewallRuleDO ruleDo=new FirewallRuleDO();
                ruleDo.setInfoId(approveProcessDO.getInfoId());
                ruleDo.setServiceProtocol(rule.getServiceProtocol());
                ruleDo.setDestinationAddress(rule.getDestinationAddress());
                ruleDo.setRuleOrder(rule.getRuleOrder());
                ruleDo.setSourceAddress(rule.getSourceAddress());
                ruleDo.setId(UUID.randomUUID().toString().replace("-", ""));
                firewallRuleMapper.insert(ruleDo);
            }
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int ApplicationUpdata(FirewallDto dataDto) {
        int result = 0;
        //设置状态
        if (!StringUtils.isEmpty(dataDto.getApplyUser()) && !StringUtils.isEmpty(dataDto.getInfoId())){
            //新增流程表
            FirewallDO dataDo=new FirewallDO();
            BeanUtils.copyProperties(dataDto, dataDo);
            //新增基础表
            LambdaQueryWrapper<FirewallDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FirewallDO::getInfoId,dataDto.getInfoId());
            result=firewallMapper.update(dataDo,queryWrapper);
            List<FirewallRuleDto> rules = dataDto.getRules();
            List<FirewallRuleDO> firewallRuleDOList = firewallRuleMapper.selectList(
                    new LambdaQueryWrapper<FirewallRuleDO>()
                            .eq(FirewallRuleDO::getInfoId, dataDto.getInfoId())
            );
            Set<String> dbAssessmentIds = firewallRuleDOList.stream()
                    .map(FirewallRuleDO::getId)
                    .collect(Collectors.toSet());
            Set<String> incomingAssessmentIds = new HashSet<>();
            if (ObjectUtil.isNotEmpty(rules)) {
                for (FirewallRuleDto assessment : rules) {
                    FirewallRuleDO assessmentDo = new FirewallRuleDO();
                    BeanUtils.copyProperties(assessment, assessmentDo);
                    assessmentDo.setInfoId(dataDto.getInfoId());
                    if (ObjectUtil.isEmpty(assessment.getId())) {
                        assessmentDo.setId(UUID.randomUUID().toString().replace("-", ""));
                        firewallRuleMapper.insert(assessmentDo);
                    } else {
                        incomingAssessmentIds.add(assessment.getId());
                        firewallRuleMapper.update(assessmentDo,
                                new LambdaQueryWrapper<FirewallRuleDO>()
                                        .eq(FirewallRuleDO::getId, assessment.getId()));
                    }
                }
            }
            Set<String> assessmentIdsToDelete = dbAssessmentIds.stream()
                    .filter(id -> !incomingAssessmentIds.contains(id))
                    .collect(Collectors.toSet());
            if (!assessmentIdsToDelete.isEmpty()) {
                firewallRuleMapper.delete(
                        new LambdaQueryWrapper<FirewallRuleDO>()
                                .in(FirewallRuleDO::getId, assessmentIdsToDelete)
                );
            }
        }
        if (!ObjectUtil.isEmpty(dataDto.getProcessStatus()) && dataDto.getProcessStatus().equals("010")) {
           //修改流程表状态为00待提交
            LambdaUpdateWrapper<ApproveProcessDO> updateWrapper=new LambdaUpdateWrapper<>();
            updateWrapper.eq(ApproveProcessDO::getProcessId,dataDto.getProcessId())
                            .set(ApproveProcessDO::getProcessStatus, "00");
            int updateCount =approveProcessMapper.update(null,updateWrapper);
            //并且删除对应流程信息表信息
            LambdaQueryWrapper<ApproveProcessRecordDO> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.eq(ApproveProcessRecordDO::getRecordId, dataDto.getProcessId());
            int de=approveProcessRecordMapper.delete(deleteWrapper);
            List<FirewallRuleDto> rules = dataDto.getRules();
            List<FirewallRuleDO> firewallRuleDOList = firewallRuleMapper.selectList(
                    new LambdaQueryWrapper<FirewallRuleDO>()
                            .eq(FirewallRuleDO::getInfoId, dataDto.getInfoId())
            );
            Set<String> dbAssessmentIds = firewallRuleDOList.stream()
                    .map(FirewallRuleDO::getId)
                    .collect(Collectors.toSet());
            Set<String> incomingAssessmentIds = new HashSet<>();
            if (ObjectUtil.isNotEmpty(rules)) {
                for (FirewallRuleDto assessment : rules) {
                    FirewallRuleDO assessmentDo = new FirewallRuleDO();
                    BeanUtils.copyProperties(assessment, assessmentDo);
                    assessmentDo.setInfoId(dataDto.getInfoId());
                    if (ObjectUtil.isEmpty(assessment.getId())) {
                        assessmentDo.setId(UUID.randomUUID().toString().replace("-", ""));
                        firewallRuleMapper.insert(assessmentDo);
                    } else {
                        incomingAssessmentIds.add(assessment.getId());
                        firewallRuleMapper.update(assessmentDo,
                                new LambdaQueryWrapper<FirewallRuleDO>()
                                        .eq(FirewallRuleDO::getId, assessment.getId()));
                    }
                }
            }
            Set<String> assessmentIdsToDelete = dbAssessmentIds.stream()
                    .filter(id -> !incomingAssessmentIds.contains(id))
                    .collect(Collectors.toSet());
            if (!assessmentIdsToDelete.isEmpty()) {
                firewallRuleMapper.delete(
                        new LambdaQueryWrapper<FirewallRuleDO>()
                                .in(FirewallRuleDO::getId, assessmentIdsToDelete)
                );
            }
            return (updateCount > 0 || de > 0) ? 1 : 0;
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int Applicationdel(FirewallDto dataDto) {
        int result = 0;
        //设置申请时间
        if (!StringUtils.isEmpty(dataDto.getInfoId())){
            //删除流程表
            LambdaQueryWrapper<ApproveProcessDO> queryWrappers = new LambdaQueryWrapper<>();
            queryWrappers.eq(ApproveProcessDO::getInfoId,dataDto.getInfoId());
            int updateCount =approveProcessMapper.delete(queryWrappers);
            //删除基础表
            LambdaQueryWrapper<FirewallDO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(FirewallDO::getInfoId,dataDto.getInfoId());
            int deleteCount=firewallMapper.delete(queryWrapper);
            LambdaQueryWrapper<FirewallRuleDO> queryWrapperRule = new LambdaQueryWrapper<>();
            queryWrapperRule.eq(FirewallRuleDO::getInfoId,dataDto.getInfoId());
            int deleteRuleCount=firewallRuleMapper.delete(queryWrapperRule);
            return  (updateCount > 0 || deleteCount > 0 || deleteRuleCount>0) ? 1 : 0;
        }
        return result;
    }

    @Override
    public List<FirewallVo> queryFirewallData(FirewallDto dataDto) {
        List<FirewallVo> list=new ArrayList<>();
        dataDto.setInfoType("4");
        if (!StringUtils.isEmpty(dataDto.getUserCode())){
            dataDto.setOffset(dataDto.getOffsetNum());
             list = firewallMapper.queryFirewallData(dataDto);
            for (FirewallVo firewallVo : list) {
                List<FirewallRuleVo> firewallRuleVos = firewallRuleMapper.queryFirewallRuleDataById(firewallVo.getInfoId());
                firewallVo.setRules(firewallRuleVos);
            }
        }
        return list;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int ApplicationSubmit(FirewallDto dataDto) {
        int result = 0;
        //当前审批id和选择的审批用户id必传
        if (!StringUtils.isEmpty(dataDto.getExamineUserId()) && !StringUtils.isEmpty(dataDto.getProcessId())){
            //修改流程表
            LambdaQueryWrapper<ApproveProcessDO> queryWrappers = new LambdaQueryWrapper<>();
            queryWrappers.eq(ApproveProcessDO::getProcessId,dataDto.getProcessId());
            ApproveProcessDO approveProcessDO=new ApproveProcessDO();
            approveProcessDO.setProcessStatus("02");//待审核
            //修改审批表对应流程状态
            int updateCount =approveProcessMapper.update(approveProcessDO,queryWrappers);
            //新增审批表流程信息表
            ApproveProcessRecordDO approveProcessRecordDO=new ApproveProcessRecordDO();
            approveProcessRecordDO.setProcessStatus("02");//待审核第一步
            approveProcessRecordDO.setExamineUserId(dataDto.getExamineUserId());//审批用户id
            approveProcessRecordDO.setRecordId(dataDto.getProcessId());
            int deleteCount = approveProcessRecordMapper.insert(approveProcessRecordDO);
            return (updateCount > 0 || deleteCount > 0) ? 1 : 0;
        }
        return result;
    }

    @Override
    public int ApplicationWithdraw(FirewallDto dataDto) {
        //
        int result = 0;
        if (!StringUtils.isEmpty(dataDto.getProcessStatus()) && !StringUtils.isEmpty(dataDto.getProcessId())){
            //修改当前流程为待提交
            LambdaUpdateWrapper<ApproveProcessDO> updateWrapper=new LambdaUpdateWrapper<>();
            updateWrapper.eq(ApproveProcessDO::getProcessId,dataDto.getProcessId())
                    .set(ApproveProcessDO::getProcessStatus, "00");
                    int updateCount =approveProcessMapper.update(null,updateWrapper);
            //删除流程记录表
            LambdaQueryWrapper<ApproveProcessRecordDO> deleteWrapper = new LambdaQueryWrapper<>();
            deleteWrapper.eq(ApproveProcessRecordDO::getRecordId, dataDto.getProcessId());
            int deleteCount = approveProcessRecordMapper.delete(deleteWrapper);
            return (updateCount > 0 || deleteCount > 0) ? 1 : 0;
        }
        return result;
    }
}
